package handler

import (
	"encoding/json"
	"io"
	"net/http"

	"backend/database"

	"gorm.io/gorm"
)

// CategoryRequest 分类请求结构
type CategoryRequest struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	ParentID    *uint  `json:"parent_id"`
}

// ListCategories 获取分类列表
func (h *Handler) ListCategories(w http.ResponseWriter, r *http.Request) {
	var categories []database.Category

	// 获取顶级分类（没有父分类的分类）
	query := h.DB.Model(&database.Category{})
	if r.URL.Query().Get("all") != "true" {
		query = query.Where("parent_id IS NULL")
	}

	// 查询分类
	result := query.Find(&categories)
	if result.Error != nil {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	// 递归预加载所有子分类
	if err := database.RecursivePreload(h.DB, &categories); err != nil {
		respondWithError(w, http.StatusInternalServerError, err.Error())
		return
	}

	respondWithJSON(w, http.StatusOK, categories)
}

// GetCategory 获取单个分类
func (h *Handler) GetCategory(w http.ResponseWriter, r *http.Request) {
	id := GetPathParam(r, "id")
	var category database.Category

	// 获取分类详情，包括子分类和知识条目
	result := h.DB.Preload("Children").Preload("Knowledges").First(&category, id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			respondWithError(w, http.StatusNotFound, "Category not found")
			return
		}
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	respondWithJSON(w, http.StatusOK, category)
}

// CreateCategory 创建分类
func (h *Handler) CreateCategory(w http.ResponseWriter, r *http.Request) {
	var req CategoryRequest
	body, err := io.ReadAll(r.Body)
	if err != nil {
		respondWithError(w, http.StatusBadRequest, "Invalid request body")
		return
	}
	defer r.Body.Close()

	if err := json.Unmarshal(body, &req); err != nil {
		respondWithError(w, http.StatusBadRequest, err.Error())
		return
	}

	// 验证必填字段
	if req.Name == "" {
		respondWithError(w, http.StatusBadRequest, "Name is required")
		return
	}

	// 检查分类名是否已存在
	var existingCategory database.Category
	result := h.DB.Where("name = ?", req.Name).First(&existingCategory)
	if result.Error == nil {
		respondWithError(w, http.StatusBadRequest, "Category name already exists")
		return
	} else if result.Error != gorm.ErrRecordNotFound {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	// 如果有父分类ID，检查父分类是否存在
	if req.ParentID != nil {
		var parentCategory database.Category
		result = h.DB.First(&parentCategory, *req.ParentID)
		if result.Error != nil {
			if result.Error == gorm.ErrRecordNotFound {
				respondWithError(w, http.StatusBadRequest, "Parent category not found")
				return
			}
			respondWithError(w, http.StatusInternalServerError, result.Error.Error())
			return
		}
	}

	// 创建分类
	category := database.Category{
		Name:        req.Name,
		Description: req.Description,
		ParentID:    req.ParentID,
	}

	result = h.DB.Create(&category)
	if result.Error != nil {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	respondWithJSON(w, http.StatusCreated, category)
}

// UpdateCategory 更新分类
func (h *Handler) UpdateCategory(w http.ResponseWriter, r *http.Request) {
	id := GetPathParam(r, "id")
	var req CategoryRequest
	body, err := io.ReadAll(r.Body)
	if err != nil {
		respondWithError(w, http.StatusBadRequest, "Invalid request body")
		return
	}
	defer r.Body.Close()

	if err := json.Unmarshal(body, &req); err != nil {
		respondWithError(w, http.StatusBadRequest, err.Error())
		return
	}

	// 验证必填字段
	if req.Name == "" {
		respondWithError(w, http.StatusBadRequest, "Name is required")
		return
	}

	// 检查分类是否存在
	var category database.Category
	result := h.DB.First(&category, id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			respondWithError(w, http.StatusNotFound, "Category not found")
			return
		}
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	// 检查新分类名是否与其他分类重复
	var existingCategory database.Category
	result = h.DB.Where("name = ? AND id != ?", req.Name, id).First(&existingCategory)
	if result.Error == nil {
		respondWithError(w, http.StatusBadRequest, "Category name already exists")
		return
	} else if result.Error != gorm.ErrRecordNotFound {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	// 如果有父分类ID，检查父分类是否存在，并且不能将自己设为自己的父分类
	if req.ParentID != nil {
		// 不能将自己设为自己的父分类
		if *req.ParentID == category.ID {
			respondWithError(w, http.StatusBadRequest, "Cannot set category as its own parent")
			return
		}

		// 检查父分类是否存在
		var parentCategory database.Category
		result = h.DB.First(&parentCategory, *req.ParentID)
		if result.Error != nil {
			if result.Error == gorm.ErrRecordNotFound {
				respondWithError(w, http.StatusBadRequest, "Parent category not found")
				return
			}
			respondWithError(w, http.StatusInternalServerError, result.Error.Error())
			return
		}

		// 检查是否会形成循环引用
		if isCircularReference(h.DB, *req.ParentID, category.ID) {
			respondWithError(w, http.StatusBadRequest, "Circular reference detected")
			return
		}
	}

	// 更新分类
	category.Name = req.Name
	category.Description = req.Description
	category.ParentID = req.ParentID

	result = h.DB.Save(&category)
	if result.Error != nil {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	respondWithJSON(w, http.StatusOK, category)
}

// DeleteCategory 删除分类
func (h *Handler) DeleteCategory(w http.ResponseWriter, r *http.Request) {
	id := GetPathParam(r, "id")

	// 检查分类是否存在
	var category database.Category
	result := h.DB.First(&category, id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			respondWithError(w, http.StatusNotFound, "Category not found")
			return
		}
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	// 检查分类是否有子分类
	var childCount int64
	result = h.DB.Model(&database.Category{}).Where("parent_id = ?", category.ID).Count(&childCount)
	if result.Error != nil {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	if childCount > 0 {
		respondWithError(w, http.StatusBadRequest, "Category has child categories")
		return
	}

	// 检查分类是否有知识条目
	var knowledgeCount int64
	result = h.DB.Model(&database.Knowledge{}).Where("category_id = ?", category.ID).Count(&knowledgeCount)
	if result.Error != nil {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	if knowledgeCount > 0 {
		respondWithError(w, http.StatusBadRequest, "Category has knowledge entries")
		return
	}

	// 删除分类
	result = h.DB.Delete(&category)
	if result.Error != nil {
		respondWithError(w, http.StatusInternalServerError, result.Error.Error())
		return
	}

	respondWithJSON(w, http.StatusOK, map[string]string{"message": "Category deleted successfully"})
}

// isCircularReference 检查是否会形成循环引用
func isCircularReference(db *gorm.DB, parentID, childID uint) bool {
	// 如果父分类就是子分类，则形成循环引用
	if parentID == childID {
		return true
	}

	// 递归检查父分类的父分类
	var parent database.Category
	result := db.First(&parent, parentID)
	if result.Error != nil {
		return false
	}

	// 如果父分类没有父分类，则不会形成循环引用
	if parent.ParentID == nil {
		return false
	}

	// 递归检查父分类的父分类是否会形成循环引用
	return isCircularReference(db, *parent.ParentID, childID)
}
